﻿#include "ssMySQLPool.h"
#include "thread/ssThread.h"
#include "dump/ssException.h"


namespace StarSeeker
{

ssMySQLPool::ssMySQLPool()
{
}

ssMySQLPool::~ssMySQLPool()
{
	WaitForExit();
}

void ssMySQLPool::Init(const char *pIP, u32 port, const char *pAccount, const char *pPW, const char *pDBName, u32 count)
{
	SS_MUTEX_LOCK(m_lock)
		if (count && m_free.empty())
		{
			for (u32 i = 0; i < count; ++i)
			{
				ssMySQLStmtQuery* pConn = new ssMySQLStmtQuery();
				pConn->Init(pIP, port, pAccount, pPW, pDBName);
				m_free.push_back(pConn);
				m_all.push_back(pConn);
			}
		}
	SS_MUTEX_UNLOCK(m_lock)
}

void ssMySQLPool::WaitForExit()
{
	while (true)
	{
		SS_LOCK_GUARD(m_lock)
		if (m_all.empty())
		{
			break;
		}
		else if (m_free.size() == m_all.size())
		{
			for (u32 i = 0; i < m_all.size(); ++i)
			{
				delete m_all[i];
			}
			m_all.clear();
			m_free.clear();
			break;
		}
		else
		{
			ssThread::Sleep(500);
		}
	}
}

void ssMySQLPool::SetCharacter(const char *pc)
{
	SS_LOCK_GUARD(m_lock)
	for (u32 i = 0; i < m_all.size(); ++i)
	{
		m_all[i]->SetCharacter(pc);
	}
}


void ssMySQLPool::SelectDB(const char *pDBName)
{
	SS_LOCK_GUARD(m_lock)
	for (u32 i = 0; i < m_all.size(); ++i)
	{
		m_all[i]->SelectDB(pDBName);
	}
}

StarSeeker::ssMySQLStmtQuery* ssMySQLPool::GetConnection()
{
	ssMySQLStmtQuery* ret = 0;
	SS_MUTEX_LOCK(m_lock)
		if (!m_free.empty())
		{
			ret = m_free.front();
			m_free.pop_front();
			ret->m_free = false;
		}
	SS_MUTEX_UNLOCK(m_lock)
	return ret;
}

void ssMySQLPool::ReleaseConnection(ssMySQLStmtQuery* pConn)
{
	SS_MUTEX_LOCK(m_lock)
		pConn->m_free = true;
		m_free.push_back(pConn);
	SS_MUTEX_UNLOCK(m_lock)
}

void ssMySQLPool::ClearAllBuffer()
{
	SS_LOCK_GUARD(m_lock)
	for (u32 i = 0; i < m_all.size(); ++i)
	{
		if (m_all[i]->m_free)
		{
			m_all[i]->CleanBuffer();
		}
	}
}

bool ssMySQLPool::AddPrepare(u32 id, const char* pIn, const char* pOut, const char* pSql, const u8 resultFlag)
{
	for (u32 i = 0; i < m_all.size(); ++i)
	{
		if (m_all[i]->PrepareQuery(id, pIn, pOut, pSql, resultFlag))
		{
			return false;
		}
	}
	return true;
}

}
